<template>
  <div class="rating-container" :style="{ gap }">
    <div
        v-for="index in maxRating"
        :key="index"
        class="star-wrapper"
        :style="{
        marginRight: gap,
        width: size,
        height: size,
        cursor: computedCursor
      }"
        @click="handleClick(index)"
        @mousemove="handleMouseMove($event, index)"
        @mouseleave="handleMouseLeave"
    >
      <component
          :is="currentIcon"
          :style="getStarStyle(index)"
          :class="{ 'half-star': isHalfStar(index) }"
      />
    </div>
  </div>
</template>

<script setup>
import { computed, ref, defineProps, defineEmits } from 'vue'
import StartIcon from '../icons/StarIcon.vue';

const props = defineProps({
  modelValue: { type: Number, default: 0 },
  maxRating: { type: Number, default: 5 },
  allowHalfStar: { type: Boolean, default: false },
  disabled: { type: Boolean, default: false },
  activeColor: { type: String, default: '#ffd700' },
  inactiveColor: { type: String, default: '#d8d8d8' },
  size: { type: String, default: '24px' },
  readonly: { type: Boolean, default: false },
  icon: { type: [Object, String], default: null },
  gap: { type: String, default: '2px' }
})

const emit = defineEmits([
  'update:modelValue',
  'change',
  'hover'
])

const hoverValue = ref(0)
const isHovering = ref(false)

// 默认的星星图标
const StarIcon = StartIcon

const currentIcon = computed(() => {
  return props.icon || StarIcon
})

const computedCursor = computed(() => {
  return props.disabled || props.readonly ? 'default' : 'pointer'
})

const getStarColor = (index) => {
  const rating = isHovering.value ? hoverValue.value : props.modelValue
  return index <= rating ? props.activeColor : props.inactiveColor
}

const getStarStyle = (index) => ({
  width: props.size,
  height: props.size,
  color: getStarColor(index)
})

const isHalfStar = (index) => {
  if (!props.allowHalfStar) return false
  const rating = isHovering.value ? hoverValue.value : props.modelValue
  return rating >= index - 1 && rating < index
}

const handleClick = (index) => {
  if (props.disabled || props.readonly) return

  let newValue = index
  if (props.allowHalfStar) {
    newValue = index - 0.5
  }

  emit('update:modelValue', newValue)
  emit('change', newValue)
}

const handleMouseMove = (event, index) => {
  if (props.disabled || props.readonly) return

  isHovering.value = true
  let newHoverValue = index

  if (props.allowHalfStar) {
    const rect = event.target.getBoundingClientRect()
    const offsetX = event.clientX - rect.left
    newHoverValue = index - (offsetX < rect.width / 2 ? 0.5 : 0)
  }

  hoverValue.value = newHoverValue
  emit('hover', newHoverValue)
}

const handleMouseLeave = () => {
  isHovering.value = false
  hoverValue.value = 0
}
</script>

<style scoped>
.rating-container {
  display: flex;
  align-items: center;
}

.star-wrapper {
  position: relative;
  display: inline-flex;
}

.half-star::before {
  content: '';
  position: absolute;
  width: 50%;
  height: 100%;
  background: inherit;
  clip-path: inset(0 50% 0 0);
}
</style>